package main

import (
	"os"
	"fmt"
	"net"
)
/*启动服务器
	port：端口
*/
func StartServer(port string) {
	// 服务地址端口
	service := ":" + port
	tcpAddr, e := net.ResolveTCPAddr("tcp4", service)

	checkError(e,"ResolveTCPAddr")

	// 启动监听
	listener, e := net.ListenTCP("tcp", tcpAddr)

	checkError(e,"ListenTCP")

	//一个map的数据结构 用来存放所有的链接
	conns := make(map[string]net.Conn)
	// 用来传递信息的 channel
	messages := make(chan string,10)

	//启动服务器广播线程
	go echoHandler(&conns,messages)

	for {
		fmt.Println("Listening ...")

		// 开始等待链接，会阻塞线程
		conn, e := listener.Accept()

		checkError(e,"listener.Accept()")
		fmt.Println("Accepting ...")

		// 将链接存入conns
		conns[conn.RemoteAddr().String()] = conn

		// 开启一个协程 用来接收数据
		go Handler(conn,messages)
	}

}
/*服务器对所有链接广播数据*/
func echoHandler(conns *map[string]net.Conn,messages chan string){
	for {

		msg := <- messages

		for key,value := range *conns {
			_, err := value.Write([]byte(msg))
			if err != nil {
				fmt.Println(err.Error())
				delete(*conns,key)
			}
		}
	}
}
/*服务器端接收数据 */
func Handler(conn net.Conn,messages chan string){
	fmt.Println("connection is connected from ",conn.RemoteAddr().String())

	buf := make([]byte,1024)

	for{
		length, err := conn.Read(buf)
		if checkError(err,"Connection") == false {
			conn.Close()
			break
		}
		if length > 0 {
			buf[length] = 0
		}
		reciveStr := string(buf[0:length])
		messages <- reciveStr
	}
}

func main() {
	if len(os.Args) != 3 {
		fmt.Println("请以正确的姿态启动...")
		os.Exit(0)
	}
	if os.Args[1] == "server"{
		StartServer(os.Args[2])
	}
	if os.Args[1] == "client" {
		StartClient(os.Args[2])
	}

}
////////////////////////////////////////////////
//
//			client
//
////////////////////////////////////////////////
func checkError(err error,info string) (res bool) {

	if err != nil{
		fmt.Println(info+"  " + err.Error())
		return false
	}
	return true
}

func StartClient(tcpaddr string)  {
	tcpAddr, e := net.ResolveTCPAddr("tcp4", tcpaddr)
	checkError(e,"client.ResolveTCPAddr")
	conn, e := net.DialTCP("tcp", nil,tcpAddr)
	checkError(e,"client.Dial")

	// 启动客户端发送线程
	go chatSend(conn)

	// 开始客户端轮询
	buf := make([]byte,1024)

	for {

		length, e := conn.Read(buf)
		if checkError(e,"client.Connection") == false {
			conn.Close()
			fmt.Println("Server is dead ...ByeBye")
			os.Exit(0)
		}
		fmt.Println(string(buf[0:length]))
	}
}
func chatSend(conn net.Conn) {
	var input string
	username := conn.LocalAddr().String()

	for {
		fmt.Scanln(&input)
		if input == "/quit" {
			fmt.Println("ByeBye ...")
			conn.Close()
			os.Exit(0)
		}
		_, e := conn.Write([]byte(username + ":  " + input))
		if e != nil {
			fmt.Println(e.Error())
			conn.Close()
			break
		}
	}
}

